This tutorial is a walkthrough a tensorflow example

Import the required libraries, this step might take some time

Loading a dataset from the tensorflow_datasets module

Since we need some data to train a predictive model on, we can leverage the tensorflow_datasets module and load some of its preprocessed datasets with a few lines of code; specifically, we will be loading the Fashion MNIST dataset from the tensorflow_datasets module.

Here is a breakdown and an explanation for the parameters that we have to set while using the tensorflow_datasets API:

The dataset object is a List of 2 Tuples, each Tuple is of length = 2 as well, and here is the logical structure of that dataset object:

[(train_images, train_labels), (test_images, test_labels)]

So, let's unpack these 2 Tuples and convert the data from Tensors to NumPy Arrays

From the above cell, we can see that our training dataset is composed of 60,000 images, each image is 28 x 28 pixels, while the testing dataset is composed of 10,000 images.

So, you might be wondering, what about the metadata; the metadata holds information about the dataset, this includes its version and the class labels. To access the labels of the classes within this dataset, we can use the following code:

Let's plot the first 2 images within the training dataset and see how do they look like and the corresponding labels

Preprocessing the data

The 28 x 28 pixels images have their pixel values ranging from 0 to 255, we will need to normalize these values to be ranging from 0 to 1, this will help the training to be faster and more stable

Split the training data into train and validation datasets

Building and training the model

Time to build our first TensorFlow model, I will leverage the high level Keras API as it makes life much easier. Also, I will break down the code in the cell below here step by step, so feel free to navigate this markdown cell and the code cell below.

Note: We need to specify the input_shape, which is the shape of each single record in the dataset, since our dataset is composed of 28 x 28 pixels images, then we should set the input_shape to (28, 28). Although, our data will be fed to the model in the form of batches of shape (batch_size x 28 x 28 x 1), the input shape of (28, 28) or (28, 28, 1) will be fine as that's what is used by the network to initialize the weights, these weights depend mainly on the number of pixels regardless the third extra dimension and so any of the 2 formats will work.

We can ignore passing an input_shape on creating the model, in such a scenario the network will figure out the shape of the data when it starts training; however, this throughs an error with the validation set with its current shape and format. So, a good practice is to pass the input_shape when creating the model.

Once the model's architecture is defined, we need to comile the model. During this step we will need to define a:

After defining the model's architecture and combiling the model, it's time to train the model. Training is the process in which the model learns the pattern mapping the inputs to the outputs. To train the model, we use the .fit() method. The parameters defined below are:

Evaluating the model

Once the model completes the training process, it's time to evaluate the model and its predictions. The Keras model object has a history attribute which can be used to load information about the model performance during training

I will first define 2 helper functions that can be used to plot the graphs for the training history of the model

Note:

At first we might be thinking the model is underfitting during the first few epochs, since we can see the model performance over the validation data Green Line is better than the performance over the training data Red Line. However, that's not true since the Red Line is the calculated as a running average and that's why I added a Blue Line which represents the model performance on the training data After each training epoch and not During the training epoch

testing the model's performance over the test set

Understanding the output of the model

If you recall, our test set consists of 1,000 images, each image is a numpy array of shape = 28 x 28 x 1, while the label for each image is an integer that corresponds to the index of the class

Our model expects the inputs to be in the following shape (batch_size x 28 x 28), so if we would like to feed our model a single image, the batch_size in this case will equal to 1, and therefore we will need to add an extra dimension to our image. This can be done using the numpy.expand_dims method, check the cell below to see how this method works

We notice the output of the network is not a single class name, it's 10 values which correspond to the probability distribution for the 10 classes that we have. The first value "at index = 0" corresponds to the probability that the input has a class label = 0, the second value "at index = 1" corresponds to the probability that the input has a class label = 1 and so on.

From this we can conclude that the sum of the 10 predicted probabilities for any input image should equal 1, we will verify that at the code cell below. For sure we can convert these classes from integers to human readable strings by using the class_names list that we defined earlier using the metadata of our dataset.

So what the model did for us when we called the .evaluate method is that it grabbed the index of the class with the highest probability, this is converted to the class with the highest probaility from the models predictions, and then the model compared this predicted class with the true class to calculate the accuracy. Let's walk through what the model did step by step

To grab the index with the highest probability for each input image, we can use the NumPy .argmax() method and specifying the axis = 1

Now we will create a Pandas DataFrame that will help us to evaluate our model's predictions further, the DataFrame will have 3 columns, a True_Class column that holds the index of the True Label, a Predicted_Class column that holds the index of the predicted class and an Is_Correct column which is a boolean of whether the model's prediction is correct or not

We notice we got the same accuracy as calculated before using the model.evaluate method. So now we will create a simple report that will help us to further evaluate the model over the different classes in the dataset

The steps above can be implemented in the form of a function since we might need to generate that report once again within this notebook

The model is not performing well on Class 6 which corresponds to Shirts, so let's see the model's predictions for some Shirt images.

First, I will introduce a helper function that will be used to plot the images and the probability distribution for the images

The function will take 4 arguments which are:

Let's test the helper function over the first 10 images within the test set

Now, let's grab the indices of the first 20 Shirt images within our test set and use the helper function above to check the True class and the Predicted class for them

From the photos above, we can see that some Shirt photos are mistkaenly classified as other tops like Pullover or T-shirt photos, and even the human eyes can hardly distinguish between these classes especially for photos of low resolution like in our case here. Later we will try other techniques that can help in improving our model's predictions.

Saving and loading Keras models

In Keras, saving the model is very simple, just use the model.save() method and pass the directory that you would like to save the model at. This saves the model so that you can use it later for predictions without having to train the model from scratch. Also, you can further train the model after loading it if you would like